package com.lixun.passwordbook.slice;

import com.lixun.passwordbook.ResourceTable;
import com.lixun.passwordbook.custom.CustomDialog;
import com.lixun.passwordbook.pojo.Colors;
import com.lixun.passwordbook.pojo.Constant;
import com.lixun.passwordbook.pojo.Data;
import com.lixun.passwordbook.util.AESUtils;
import com.lixun.passwordbook.util.FileData;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.aafwk.content.Intent;
import ohos.agp.components.*;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.IDialog;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;
import ohos.data.dataability.DataAbilityPredicates;
import ohos.data.rdb.ValuesBucket;
import ohos.data.resultset.ResultSet;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.utils.net.Uri;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import static ohos.agp.components.ComponentContainer.LayoutConfig.MATCH_CONTENT;

public class SetAbilitySlice extends AbilitySlice {
    static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "SetStart");
    private Context mContext;
    private Text resultText;
    private final String FACE_KEY="xswlawsl!lspyyds";
    private static final String BASE_URI = "dataability:///com.lixun.passwordbook.DataAbility";
    private static final String DATA_PATH = "/pwb";
    private static final String DB_COLUMN_PASSWORD = "password";
    private static final String DB_COLUMN_ID = "id";
    private DataAbilityHelper databaseHelper;
    private ArrayList<Data> fileList = new ArrayList();

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_set);
        databaseHelper = DataAbilityHelper.creator(this);
        mContext = this;
        //创建返回按钮
        createReturnBtn();
        //创建面部开关
        createFaceSwitch();
        //设置状态栏颜色
        setStatusBarColor();
        //设置颜色模式
        colorMode();
        //修改密码弹窗
        initComponents();
        //创建隐私政策按钮
        setPrivacyBtn();
    }

    /**
     * 设置状态栏颜色
     */
    private void setStatusBarColor() {
        getWindow().addFlags(WindowManager.LayoutConfig.MARK_TRANSLUCENT_NAVIGATION);
        getWindow().setStatusBarColor(Color.TRANSPARENT.getValue());
    }

    /**
     * 颜色模式切换
     */
    private void colorMode(){
        DirectionalLayout abilitySet = (DirectionalLayout) findComponentById(ResourceTable.Id_ability_set);
        Button pwd = (Button) findComponentById(ResourceTable.Id_ability_set_pwd);
        DirectionalLayout face = (DirectionalLayout) findComponentById(ResourceTable.Id_ability_set_face);
        Button time = (Button) findComponentById(ResourceTable.Id_ability_set_privacy);
        Text faceText = (Text) findComponentById(ResourceTable.Id_ability_set_face_text);
        Text text = (Text) findComponentById(ResourceTable.Id_ability_set_text);
        Button returnBtn = (Button)findComponentById(ResourceTable.Id_set_return);
        boolean dark_mode = Colors.getDarkMode();
        ShapeElement shapeElement = new ShapeElement();
        ShapeElement element;
        Resource bgResource=null;
        Color color;
        if (dark_mode){
            HiLog.info(LABEL, "设置为深色模式");
            shapeElement.setRgbColor(Colors.backgroundColorDark);
            element = new ShapeElement(mContext,ResourceTable.Graphic_item_background_dark);
            color = Colors.textColorDark;
        } else {
            HiLog.info(LABEL, "设置为常规模式");
            shapeElement.setRgbColor(Colors.backgroundColor);
            element = new ShapeElement(mContext,ResourceTable.Graphic_item_background);
            color = Colors.textColor;
        }
        try {
            if (dark_mode){
                bgResource =getResourceManager().getResource(ResourceTable.Media_detailed_return_dark);
            } else {
                bgResource =getResourceManager().getResource(ResourceTable.Media_detailed_return);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        }
        abilitySet.setBackground(shapeElement);
        pwd.setBackground(element);
        face.setBackground(element);
        time.setBackground(element);
        pwd.setTextColor(color);
        time.setTextColor(color);
        faceText.setTextColor(color);
        text.setTextColor(color);
        PixelMapElement pixBg=new PixelMapElement(bgResource);
        returnBtn.setAroundElements(pixBg,null,null,null);
    }

    /**
     * 创建返回按钮
     */
    private void createReturnBtn(){
        Component component = findComponentById(ResourceTable.Id_set_return);
        Button typeSelect;
        if (component instanceof Button) {
            typeSelect = (Button) component;
            typeSelect.setClickedListener(view -> {
                terminate();
            });
        }
    }

    /**
     * 创建面部识别开关
     */
    private void createFaceSwitch(){
        Switch btnSwitch = (Switch) findComponentById(ResourceTable.Id_set_face_switch);
        //获取switch状态设置，默认false
        Context context = getApplicationContext();
        FileData fileData = new FileData();
        boolean face_switch = fileData.getBoolean(context,"face_switch",false);
        //设置Switch默认状态
        btnSwitch.setChecked(face_switch);
        btnSwitch.setCheckedStateChangedListener(new AbsButton.CheckedStateChangedListener() {
            // 回调处理Switch状态改变事件
            @Override
            public void onCheckedChanged(AbsButton button, boolean isChecked) {
                fileData.setBoolean(context,"face_switch",isChecked);
            }
        });
    }

    /**
     * 创建修改面膜弹出（自定义Dialog）
     */
    private void initComponents() {
        Component customDialogButton = findComponentById(ResourceTable.Id_ability_set_pwd);
        resultText = (Text) findComponentById(ResourceTable.Id_result_text);
        customDialogButton.setClickedListener(component -> showCustomDialog());
    }

    /**
     * 创建修改面膜弹出（自定义Dialog）
     */
    private void setPrivacyBtn() {
        Component customDialogButton = findComponentById(ResourceTable.Id_ability_set_privacy);
        customDialogButton.setClickedListener(component -> privacyDialog());
    }

    /**
     * 修改密码弹窗
     */
    private void showCustomDialog() {
        CustomDialog customDialog = new CustomDialog(this);
        customDialog.setAutoClosable(true);
        customDialog.setOnConfirmListener(string -> {
            Constant.setNewKEY(string);
            if (correctPWD()){
                setPWD(stringToMD5(string));
                setData(string);
                Constant.setKEY(string);
            } else {
                //设置失败后还原数据
                reductionPWD();
            }
            resultText.setText(string);
            customDialog.destroy();
        });
        customDialog.show();
    }

    /**
     * 设置面部识别成功后提取的密码
     * @param key 传入密钥
     * @return 判断是否成功
     */
    private Boolean setData(String key) {
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.equalTo(DB_COLUMN_ID, 1);
        ValuesBucket valuesBucket = new ValuesBucket();
        valuesBucket.putString(DB_COLUMN_PASSWORD, AESUtils.encrypt(FACE_KEY,key));
        try {
            if (databaseHelper.update(Uri.parse(BASE_URI + DATA_PATH), valuesBucket, predicates) != -1) {
                HiLog.info(LABEL, "update 成功");
                return true;
            }
        } catch (DataAbilityRemoteException | IllegalStateException exception) {
            HiLog.error(LABEL, "update: dataRemote exception | illegalStateException");
        }
        return false;
    }

    /**
     * MD5加密
     * @param plainText 需要转换的数据
     * @return 转换后的数据
     */
    public static String stringToMD5(String plainText) {
        byte[] secretBytes = null;
        String newText = plainText + Constant.SALT;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(
                    newText.getBytes());
            HiLog.info(LABEL,"md5 yes");
        } catch (NoSuchAlgorithmException e) {
            HiLog.info(LABEL,"没有这个md5算法");
            throw new RuntimeException("没有这个md5算法！");
        }
        String md5code = new BigInteger(1, secretBytes).toString(16);
        for (int i = 0; i < 32 - md5code.length(); i++) {
            md5code = "0" + md5code;
        }
        return md5code;
    }

    /**
     * 设置文本数据
     * @param pwd pwd
     */
    private void setPWD(String pwd){
        Context context = getApplicationContext();
        FileData fileData = new FileData();
        fileData.setBoolean(context,"first",false);
        fileData.setString(context,"lxpwd",pwd);
    }

    /**
     * 更正密码
     * @return 判断是否成功
     */
    private boolean correctPWD(){
        List<Data> list = getData();
        for (Data data : list){
            if (updatePWD(data)){
                fileList.add(data);
            } else {
                return false;
            }
        }
        return true;
    }

    /**
     * 还原密码
     */
    private void reductionPWD(){
        for (Data data : fileList){
            if (reductionPWD(data)){
                HiLog.info(LABEL,"还原成功");
            }
        }
    }

    /**
     * 获取数据
     * @return 获取数据集合
     */
    private ArrayList<Data> getData() {
        String[] columns = new String[]{DB_COLUMN_ID,DB_COLUMN_PASSWORD};
        // 构造查询条件
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.notEqualTo(DB_COLUMN_ID, 1);
        try {
            ResultSet resultSet = databaseHelper.query(Uri.parse(BASE_URI + DATA_PATH),
                    columns, predicates);
            if (resultSet == null || resultSet.getRowCount() == 0) {
                HiLog.info(LABEL, "query: resultSet is null or no result found");
                return null;
            }
            resultSet.goToFirstRow();
            ArrayList<Data> list = new ArrayList();
            Data data;
            do {
                int id = resultSet.getInt(resultSet.getColumnIndexForName(DB_COLUMN_ID));
                String bytepwd = resultSet.getString(resultSet.getColumnIndexForName(DB_COLUMN_PASSWORD));
                String password;
                //如果密码未设置，则不经过转换，否则会出现错误提示app正常运行
                if (bytepwd == null || bytepwd.length() ==0 || bytepwd.equals("")){
                    password = bytepwd;
                } else {
                    password = AESUtils.decrypt(Constant.getKEY(),bytepwd);
                }
                data = new Data(id,password);
                list.add(data);
            } while (resultSet.goToNextRow());
            return list;
        } catch (DataAbilityRemoteException | IllegalStateException exception) {
            HiLog.error(LABEL, "query: dataRemote exception | illegalStateException");
        }
        return null;
    }

    /**
     * 修改密码
     * @param data data
     * @return 判断是否插入成功
     */
    private Boolean updatePWD(Data data) {
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.equalTo(DB_COLUMN_ID, data.getId());
        ValuesBucket valuesBucket = new ValuesBucket();
        String password = data.getPassword();
        if (password == null || password.length() == 0){
        } else {
            password = AESUtils.encrypt(Constant.getNewKEY(),password);
        }
        valuesBucket.putString(DB_COLUMN_PASSWORD, password);
        try {
            if (databaseHelper.update(Uri.parse(BASE_URI + DATA_PATH), valuesBucket, predicates) != -1) {
                HiLog.info(LABEL, "update 密码成功");
                return true;
            }
        } catch (DataAbilityRemoteException | IllegalStateException exception) {
            HiLog.error(LABEL, "update: dataRemote exception | illegalStateException");
        }
        return false;
    }

    /**
     * 还原密码
     * @param data data
     * @return 判断是否插入成功
     */
    private Boolean reductionPWD(Data data) {
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.equalTo(DB_COLUMN_ID, data.getId());
        ValuesBucket valuesBucket = new ValuesBucket();
        String password = data.getPassword();
        if (password == null || password.length() == 0){
        } else {
            password = AESUtils.encrypt(Constant.getKEY(),password);
        }
        valuesBucket.putString(DB_COLUMN_PASSWORD, password);
        try {
            if (databaseHelper.update(Uri.parse(BASE_URI + DATA_PATH), valuesBucket, predicates) != -1) {
                HiLog.info(LABEL, "update 密码成功");
                return true;
            }
        } catch (DataAbilityRemoteException | IllegalStateException exception) {
            HiLog.error(LABEL, "update: dataRemote exception | illegalStateException");
        }
        return false;
    }

    /**
     * 提示隐私政策
     */
    private void privacyDialog() {

        CommonDialog dialog = new CommonDialog(getContext());
        dialog.setTitleText("隐私政策");
        dialog.setButton(IDialog.BUTTON2, "好的", (iDialog, i) -> iDialog.destroy());
        Component container = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_ability_welcome_privacy_dialog, null, false);
        dialog.setContentCustomComponent(container);
        dialog.setSize(MATCH_CONTENT, MATCH_CONTENT);
        dialog.show();
    }
}
